****CODE TO PERFORM THE PROPENSITY SCORE MATCHING
use pseudo_data.dta, clear

*** FIRST, GENERATE VARIABLES
*create panel
encode isin, gen(firm_code)
xtset firm_code fy
*log of total assets
gen ln_ta=ln(ta)
replace ln_ta=ln(tle) if ln_ta==.
*leverage
gen lev=td/ta 
replace lev=td/tle if lev==.
*profitability (net income to total assets)
gen ni_ta=nibt/ta
replace ni_ta=nibt/tle if ni_ta==.
*firm age
gen ln_age=ln(fy-year_founded)
replace ln_age=0 if ln_age==.
*TobinQ
gen tobinq=(enterprise_value/1000)/ta
replace tobinq=(enterprise_value/1000)/tle if tobinq==.
replace tobinq=(enterprise_value/1000)/(te+tl) if tobinq==.
*CAPEX (to total assets)
gen capex_ta=capex/ta
replace capex_ta=capex/tle if capex_ta==.
*log of board size
gen ln_bsize=ln(boardsize)
*log of board tenure
gen ln_btenure=ln(avgboardtenure+1)
*board gender diversity (take the variable in %)
replace boardgenderdiv=boardgenderdiv/100
*ESP score (reweighting the ESG score after excluding the "G")
gen es_weight=e_emiss_weight+e_inn_weight+e_res_weight+s_hr_weight+s_pr_weight+s_work_weight+s_comm_weight
gen s_es=s_esg_e_res*(e_res_weight/es_weight)+s_esg_e_emiss*(e_emiss_weight/es_weight)+s_esg_e_inn*(e_inn_weight/es_weight)+s_esg_s_hr*(s_hr_weight/es_weight)+s_esg_s_pr*(s_pr_weight/es_weight)+s_esg_s_work*(s_work_weight/es_weight)+s_esg_s_comm*(s_comm_weight/es_weight)

save db_full.dta, replace

*** THEN, RUN PROPENSITY SCORE MATCHING
*** the following commands to keep only firm-years in which relevant variables must not be missing in t-1 and t+1
gen suitable=1 if s_esg_e!=. & s_esg_s!=. & s_es!=. & ln_ta!=. & ni_ta!=. & lev!=. & ln_age!=. & tobinq!=. & p_ret!=. & p_vol!=. & capex_ta!=. & ln_bsize!=. & ln_btenure!=. & execompesgperf_d!=. & ceochair_d!=. & boardgenderdiv!=. & shareeng_d!=.
gen suitable_before=1 if l.suitable!=.
gen suitable_after=1 if f.suitable!=.
keep if suitable_after==1 & suitable_before==1
drop suitable suitable_after suitable_before
*** create lagged variables to be included in the 1st stage probit regression for PSM
foreach x of varlist s_esg s_esgcomb s_es s_esg_e s_esg_s ln_ta ni_ta tobinq lev ln_age p_ret p_vol capex_ta ln_bsize ln_btenure execompesgperf_d ceochair_d boardgenderdiv shareeng_d {
	gen l_`x'=l.`x'
}
*** keep only potential control firm-years and, for treated firm-years, only the 1st green bond issue FY
keep if treated==0 | (treated==1 & issue_fy==fy)
*** create groups and keep those groups in which at least a treated and a control firm-year is present
xtile g_s_es=l_s_es, nq(3)
egen g=group(trbc loc g_s_es)
egen g_treated=total(treated==1), by(g)
egen g_control=total(treated==0), by(g)
drop if g==.
drop if g_treated==0
drop if g_control==0
drop g_treated g_control
*** this is the "pre-match dataset"
save db_prematch.dta, replace

*** create an empty "horizontal" dataset to assign a pair code to each firm
foreach x of varlist isin-g {
	gen `x'_c=`x'
}
gen id_treated= .
gen id_mcontrol= .
gen _pdif= .
order id_treated id_mcontrol _pdif, after(g)
keep if isin==""
save pairs_horizontal.dta, replace

*** run the PSM for each group
use db_prematch.dta, clear
levelsof g, local(gr)
local match_covariates "l_ln_ta l_lev l_tobinq l_p_ret l_p_vol ni_ta ln_age capex_ta" 
foreach j of local gr {
	keep if g==`j'
	***"capture" in case a certain value predict perfectly
	capture psmatch2 treated `match_covariates', neighbor(1) common noreplacement
	***confirm that the PSM happened, otherwise, go ahead
	capture confirm variable _id
	if _rc != 0 {
		use db_prematch.dta, clear
	}
	else {
		***isolate the pairs
		rename _id id_treated
		rename _n1 id_mcontrol
		preserve
		keep if _nn==1
		keep id_treated id_mcontrol
		save id_treated.dta, replace
		restore, preserve
		keep if _nn==1
		keep id_mcontrol
		rename id_mcontrol id_treated
		save id_control.dta, replace
		restore, preserve
		quietly merge 1:1 id_treated using id_treated.dta
		keep if _merge==3
		drop _merge _pscore _treated _support _weight _nn
		save treated_firms_group`j'.dta, replace
		restore
		quietly merge 1:1 id_treated using id_control.dta
		keep if _merge==3
		drop _merge _pscore _treated _support _weight _nn _pdif id_mcontrol
		foreach x of varlist isin-g {
			rename `x' `x'_c
			}
		rename id_treated id_mcontrol
		save control_firms_group`j'.dta, replace
		use treated_firms_group`j'.dta, clear
		quietly merge 1:1 id_mcontrol using control_firms_group`j'.dta
		keep if _merge==3
		drop _merge
		save pairs_group`j'.dta, replace
		clear
		use pairs_horizontal.dta
		quietly merge 1:1 isin-g_c using pairs_group`j'.dta
		drop _merge
		save pairs_horizontal.dta, replace
		erase id_treated.dta
		erase id_control.dta
		erase control_firms_group`j'.dta
		erase treated_firms_group`j'.dta
		erase pairs_group`j'.dta
		clear
		use db_prematch.dta
	}
}

*** after running the PSM, create the final sample in a panel structure
use pairs_horizontal.dta, clear
gen pair_code=_n
order pair_code, before(isin_c)
gen pair_code_c=_n
rename fy fy_event
rename fy_c fy_event_c
rename treated treated_match
rename treated_c treated_match_c
gen _pdif_c=_pdif
order _pdif_c, before(pair_code_c)

keep isin fy_event treated_match _pdif pair_code isin_c fy_event_c treated_match_c _pdif_c pair_code_c
order isin fy_event treated_match _pdif pair_code isin_c fy_event_c treated_match_c _pdif_c pair_code_c
preserve
keep isin-pair_code
save pairs_horizontal_treated_temp.dta, replace
restore
keep isin_c-pair_code_c
rename isin_c isin
rename fy_event_c fy_event
rename treated_match_c treated_match
rename _pdif_c _pdif
rename pair_code_c pair_code
merge 1:1 isin fy_event treated_match _pdif pair_code using pairs_horizontal_treated_temp.dta
drop _merge
erase pairs_horizontal_treated_temp.dta
gen obs_n=_n
gen n=1
egen count_isin=sum(n), by(isin)
preserve
keep if count_isin==1
save pairs_vertical1.dta, replace
restore
keep if count_isin>1
sort isin fy_event
gen d=1 if isin==isin[_n+1]
preserve
keep if d==.
drop d
save pairs_vertical2.dta, replace
restore
keep if d==1
drop d
gen d=1 if isin==isin[_n+1]
preserve
keep if d==.
drop d
save pairs_vertical3.dta, replace
restore
keep if d==1
drop d
save pairs_vertical4.dta, replace

use db_full.dta, clear
merge m:1 isin using pairs_vertical1.dta
keep if _merge==3
drop _merge
keep if fy-fy_event<=4 & fy-fy_event>=-4
save pairs_vertical1.dta, replace
keep if isin==""
save db_did.dta, replace

forvalues x=2/3 {
	use db_full.dta, clear
	merge m:1 isin using pairs_vertical`x'.dta
	keep if _merge==3
	drop _merge
	keep if fy-fy_event<=4 & fy-fy_event>=-4
	save pairs_vertical`x'.dta, replace
}

use pairs_vertical4.dta, clear
levelsof obs_n, local(levels)
foreach l of local levels {
	keep if obs_n==`l'
	save temp`l'.dta, replace
	use db_full.dta, clear
	quietly merge m:1 isin using temp`l'.dta
	keep if _merge==3
	drop _merge
	keep if fy-fy_event<=4 & fy-fy_event>=-4
	save temp`l'.dta, replace
	use db_did.dta, clear
	quietly merge 1:1 isin-count_isin using temp`l'.dta
	drop _merge
	erase temp`l'.dta
	save db_did.dta, replace
	use pairs_vertical4.dta, clear
	*sleep 200
}
erase pairs_vertical4.dta
use db_did.dta, clear
forvalues x=1/3 {
	merge 1:1 isin-count_isin using pairs_vertical`x'.dta
	drop _merge
	erase pairs_vertical`x'.dta
}
drop firm_code
gen fy_t=fy-fy_event
rename obs_n firm_code
gen after=(fy_t>0)
xtset firm_code fy_t
***winsorize
foreach x of varlist ni_ta lev tobinq p_ret p_vol capex_ta {
	winsor2 `x', cuts(1 99) suffix(_w199)
}
erase pairs_horizontal.dta
save db_did.dta, replace
***this is the final matched sample

***********************************************************************************************
***********************************************************************************************
******************************************* FIGURES *******************************************
***********************************************************************************************
***********************************************************************************************

*** Figure 1. PROPENSITY SCORE DISTRIBUTION
preserve
keep if treated_match==1 & fy_t==0
histogram _pdif, bin(100) frequency fcolor(edkblue) lcolor(edkblue) ytitle(, margin(medsmall)) xtitle(Propensity score distribution) xtitle(, margin(medsmall))
restore

*** Figures 2a-c-e. KERNEL DENSITY (PRE-MATCH SAMPLE)
preserve
use db_prematch.dta, clear
local varplot "s_es"
kdensity `varplot', nograph generate(x fx)
kdensity `varplot' if treated==0, nograph generate(fx0) at(x)
kdensity `varplot' if treated==1, nograph generate(fx1) at(x)
label var fx0 "Potential controls"
label var fx1 "Treated group"
line fx0 fx1 x, sort ytitle("") xtitle("") title(`varplot') legend(pos(6) col(2) ring() region(lcolor(black))) xsize(5) ysize(5)
restore

*** Figures 2b-d-f. KERNEL DENSITY (POST-MATCH SAMPLE)
preserve
local varplot "s_es"
kdensity `varplot' if fy_t==-1, nograph generate(x fx)
kdensity `varplot' if treated_match==0, nograph generate(fx0) at(x)
kdensity `varplot' if treated_match==1, nograph generate(fx1) at(x)
label var fx0 "Matched controls"
label var fx1 "Treated group"
line fx0 fx1 x, sort ytitle("") xtitle("") title(`varplot') legend(pos(6) col(2) ring() region(lcolor(black))) xsize(5) ysize(5)
restore

*** Figures 3a-c-e. PARALLEL TREND: ESP - ENV - SOC
***alternate, in "local varplot" command, s_es, s_esg_e and s_esg_s
preserve
keep if fy_t!=0
local varplot "s_es"
collapse `varplot', by(fy_t treated_match)
rename treated_match treated_dummy
egen Treated=mean(`varplot') if treated_dummy==1, by(fy_t)
egen Control=mean(`varplot') if treated_dummy==0, by(fy_t)
replace Control=Control[_n-1] if Control==.
drop if Treated==.
twoway (connected Treated fy_t) (connected Control fy_t), ytitle(Mean ESP) ytitle(, margin(medsmall)) xtitle(, size(zero)) xline(0, lcolor(black%50)) xlabel(-4 "t-4" -3 "t-3" -2 "t-2" -1 "t-1" 0 "t0" 1 "t+1" 2 "t+2" 3 "t+3" 4 "t+4") legend(pos(6) col(2) ring() region(lcolor(black)))
restore

*** Figure 3b-d-f. AVERAGE TREATMENT EFFECT
***alternate, in "local varplot" command, s_es, s_esg_e and s_esg_s
preserve
local varplot "s_es"
replace fy_t=fy_t+5
forvalues x=1/9 {
reg `varplot' treated_match if fy_t==`x', rob
gen b_`x'=_b[treated_match] if fy_t==`x'
gen se_`x'=_se[treated_match] if fy_t==`x'
}
collapse b_1-se_9, by(fy_t)
gen b=.
gen se=.
forvalues x=1/9 {
	ereplace b=mean(b_`x') if b_`x'!=.
	ereplace se=mean(se_`x') if se_`x'!=.
	drop b_`x' se_`x'
}
replace fy_t=fy_t-5
keep if fy_t!=0
gen se_bottom=b-((se/b)/2)
gen se_top=b+((se/b)/2)
twoway (sc b fy_t, connect(line)) (rcap se_top se_bottom fy_t), xline(0, lcolor(black%50)) xtitle("") ytitle("") title(`varplot') xlabel(-4 "t-4" -3 "t-3" -2 "t-2" -1 "t-1" 0 "t0" 1 "t+1" 2 "t+2" 3 "t+3" 4 "t+4") legend(pos(6) col(2) ring() label(1 "Point estimate") label(2 "Std Error") region(lcolor(black))) xsize(5) ysize(5)
restore

***********************************************************************************************
***********************************************************************************************
************************************** REGRESSION TABLES **************************************
***********************************************************************************************
***********************************************************************************************

***MAIN RESULTS (Table 5)
reg s_es treated_match##after i.fy i.trbc i.loc if fy_t>-3 & fy_t<3 & fy_t!=0, rob
reg s_es treated_match##after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 i.fy i.trbc i.loc if fy_t>-3 & fy_t<3 & fy_t!=0, rob
reg s_es treated_match##after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy i.trbc i.loc if fy_t>-3 & fy_t<3 & fy_t!=0, rob
xtreg s_es treated_match##after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy if fy_t>-3 & fy_t<3 & fy_t!=0, fe vce(cluster firm_code)

*** ROBUSTNESS TESTS (Table 6)
reg s_es treated_match##after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy i.trbc i.loc if fy_t>-3 & fy_t<3 & fy_t!=0 & _pdif<0.005, rob
xtreg s_es treated_match##after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy if fy_t>-3 & fy_t<3 & fy_t!=0 & _pdif<0.005, fe vce(cluster firm_code)
reg s_es treated_match##after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy i.trbc i.loc if fy_t>-3 & fy_t<3 & fy_t!=0 & green_uop_avg!=0, rob
xtreg s_es treated_match##after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy if fy_t>-3 & fy_t<3 & fy_t!=0 & green_uop_avg!=0, fe vce(cluster firm_code)
reg s_es treated_match##after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy i.trbc i.loc if fy_t>-3 & fy_t<3 & fy_t!=0 & green_uop_avg!=0 & _pdif<0.005, rob
xtreg s_es treated_match##after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy if fy_t>-3 & fy_t<3 & fy_t!=0 & green_uop_avg!=0 & _pdif<0.005, fe vce(cluster firm_code)


*** ESG, ESG COMBINED AND SUB-PILLARS AS DEPENDENT VARIABLES (Table 7)
foreach x of varlist s_esg s_esgcomb s_esg_e s_esg_s s_esg_e_res s_esg_e_emiss s_esg_e_inn s_esg_s_work s_esg_s_hr s_esg_s_comm s_esg_s_pr {
	qui reg `x' treated_match##after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy i.trbc i.loc if fy_t>-3 & fy_t<3 & fy_t!=0, rob
}

*** CONDITION ON GREEN BOND AMOUNT (RELATIVE TO TOTAL ASSETS) (Table 8)
*** first, create variables allowing to condition on amount issued
gen amt_ta=(total_amount/1000000)/ta if fy_t==0 & treated_match==1
egen amt_ta_temp=mean(amt_ta), by(pair_code)
xtile median_amt_ta=amt_ta_temp, nq(2)
replace median_amt_ta=median_amt_ta-1
foreach x of varlist s_es s_esg_e s_esg_s {
	reg `x' treated_match##after##median_amt l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy i.trbc i.loc if fy_t>-3 & fy_t<3 & fy_t!=0, rob
	reg `x' treated_match##after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy i.trbc i.loc if fy_t>-3 & fy_t<3 & fy_t!=0 & median_amt==0, rob
	reg `x' treated_match##after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy i.trbc i.loc if fy_t>-3 & fy_t<3 & fy_t!=0 & median_amt==1, rob
}

*** CONDITION ON PRE-ISSUANCE ESG PERFORMANCE (Table 9)
*** first, create variables allowing to condition on pre-issuance ESG performance
foreach x of varlist s_es s_esg_e s_esg_s {
egen `x'_temp=total(`x') if treated_match==1 & fy_t==-1, by(pair_code)
egen `x'_temp2=mean(`x'_temp), by(pair_code)
xtile `x'_median=`x'_temp2, nq(2)
replace `x'_median=`x'_median1-1
drop `x'_temp `x'_temp2
}
foreach x of varlist s_es s_esg_e s_esg_s {
	reg `x' treated_match##after##`x'_median l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy i.trbc i.loc if fy_t>-3 & fy_t<3 & fy_t!=0, rob
	reg `x' treated_match##after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy i.trbc i.loc if fy_t>-3 & fy_t<3 & fy_t!=0 & `x'_median==0, rob
	reg `x' treated_match##after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy i.trbc i.loc if fy_t>-3 & fy_t<3 & fy_t!=0 & `x'_median==1, rob
}

*** ESG CONTROVERSIES (ESGincidents from RepRisk) (Table 10)
gen treated_after=treated_match*after
foreach x of varlist rrc_d_ungc1 rrc_d_ungc2 rrc_d_ungc3 rrc_d_ungc4 rrc_d_ungc5 rrc_d_ungc6 rrc_d_ungc7 rrc_d_ungc8 rrc_d_ungc9 rrc_d_ungc10 rrc_d_env rrc_d_soc rrc_d_gov {
logit `x' treated_match after treated_after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d i.fy_event i.trbc i.loc if fy_t>-3 & fy_t<3 & fy_t!=0, rob
margins, dydx(treated_match after treated_after l.ln_ta l.ni_ta_w199 l.lev_w199 l.ln_age l.tobinq_w199 l.p_ret_w199 l.p_vol_w199 l.capex_ta_w199 l.ln_bsize l.ln_btenure l.execompesgperf_d l.ceochair_d l.boardgenderdiv l.shareeng_d) atmeans post
}
